#library('BubbleUserAction');
#import('BubbleDrawer.dart');
#import('Bubble.dart');
#import('BubbleGrid.dart');

/** For clicking/selecting bubbles. */
class BubbleUserAction {
  
  // The list of indices of bubbles which the user has currently selected in the grid of bubbles.
  List<int> selected;
  
  // The grid of bubbles
  BubbleGrid game;
  
  // Used to for changes to the visual appearance of the game after user clicks/selects bubbles.
  BubbleDrawer drawer;
  
  // Constructor
  BubbleUserAction(BubbleDrawer drawer) {
    selected = new List();
    this.game = drawer.grid;
    this.drawer = drawer;
  }
  
  // Called when the user clicks on a bubble at the given index in the grid.
  // If the bubble is already in the selected group, remove the group.
  // If the bubble has other bubbles of the same color around it, outline the group of
  // same color bubbles. Add all their indices to the selected group.
  void clickBubble(int index) {
    drawer.outlineSelectedGroup(false, selected);
  
    // If the bubble is part of the already selected group, remove the selected group
    if (selected.indexOf(index) >= 0) {
      game.totalPoints = game.totalPoints + selected.length * (selected.length - 1);
      game.removeGroup(selected);
      game.removeEmptyColumns();
      drawer.drawGame();
    
      // Check if the game is over, and if so alert the user.
      if (game.isGameOver()) {
        drawer.alertGameOver(game.totalPoints);
      }
      
      selected = new List();
      drawer.hideSelectedPoints(true); 
    }
    else { //Otherwise, make a new selected group based on the chosen bubbles
      selected = new List();
      selectBubble(index);
      if (selected.length > 1) {
        drawer.outlineSelectedGroup(true, selected);
        drawer.hideSelectedPoints(false);
      } else {
        selected = new List();
        drawer.hideSelectedPoints(true);
      }
    drawer.setSelectPoints((selected.length * (selected.length - 1)));
    }
 }

  // Add the given bubble and all neighbours of the same color to the list of indices representing selected bubbles.
  void selectBubble(int bubble) {
    int length = game.length;
    int numBubbles = game.size();
    List<Bubble> bubbles = game.bubbles;
 
    if (bubble > -1 && bubble < numBubbles && selected.indexOf(bubble) < 0 && ( selected.length == 0 || bubbles[bubble].equals(bubbles[selected[0]]))) {
      selected.add(bubble);
      
      if ((bubble + 1) % length != 0) {
        selectBubble( bubble + 1 );
      }
      if (bubble % length != 0 ) {
        selectBubble( bubble - 1 );
      }
      if (bubble - length < numBubbles) {
        selectBubble( bubble - length );
      }
      if (bubble + length > -1 ) {
        selectBubble( bubble + length );
      }
    }
  }
}
